package com.lmaos.allcontrol.beancontrol.class_;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class MyClassLibrary {
	
	private Map<Class,MyClassLibraryCallback> myClassLibraryCallbacks = new ConcurrentHashMap<Class,MyClassLibraryCallback>(32);
	
	private static MyClassLibrary classLibrary = new MyClassLibrary();
	public static MyClassLibrary getClassLibrary() {
		return classLibrary;
	}
	private Map<String, ClassLoader> classLoaderMap = new ConcurrentHashMap<String, ClassLoader>(128);
	/** 加载 class
	 * 
	 * @param classLoaderName
	 * @param className
	 * @return
	 * @throws ClassNotFoundException 			类不存在
	 * @throws ClassLoaderNotFoundException 	类加载器不存在
	 */
	public Class loadClass(String classLoaderName,String className) throws ClassNotFoundException, ClassLoaderNotFoundException{
		Class clazz = null;
		ClassLoader classLoader = getClassLoader(classLoaderName);
		if(classLoader!=null){
			clazz = classLoader.loadClass(className);
		}else{
			throw new ClassLoaderNotFoundException(classLoaderName);
		}
		return clazz;
	}
	/** 安装一个class加载器
	 * 
	 * @param classLoaderName
	 * @param classLoader
	 * @return
	 */
	public boolean install(String classLoaderName,ClassLoader classLoader){
		if(existLoader(classLoaderName)){
			return false;
		}
		classLoaderMap.put(classLoaderName, classLoader);
		installSuccessCallback(classLoaderName, classLoader);
		return true;
	}
	/** 卸载这个class加载器
	 * 
	 * @param classLoaderName
	 * @return
	 */
	public ClassLoader uninstall(String classLoaderName){
		if(classLoaderName==null||classLoaderName.isEmpty()){
			return null;
		}
		ClassLoader classLoader_old = getClassLoader(classLoaderName);
		if(classLoader_old!=null){
			classLoaderMap.remove(classLoaderName);
			uninstallSuccessCallback(classLoaderName, classLoader_old);
		}
		return classLoader_old;
	}
	/** 卸载并且安装新的
	 * 
	 * @param classLoaderName
	 * @param classLoader
	 * @return	返回值为卸载掉的 classLoader
	 */
	public ClassLoader uninstallAndInstall(String classLoaderName,ClassLoader classLoader){
		if(classLoaderName==null||classLoaderName.isEmpty()){
			return null;
		}
		ClassLoader classLoader_old = classLoaderMap.get(classLoaderName);
		classLoaderMap.put(classLoaderName, classLoader);
		if(classLoader_old!=null){
			uninstallSuccessCallback(classLoaderName, classLoader_old);
		}
		installSuccessCallback(classLoaderName, classLoader);
		return classLoader_old;
	}
	public boolean existLoader(String classLoaderName){
		if(classLoaderName == null||classLoaderName.isEmpty()){
			return true;
		}
		return classLoaderMap.containsKey(classLoaderName);
	}
	/** 发生此异常代表查找的类加载器不存在
	 * 
	 * @author lmaos 
	 * 2016年11月29日 上午11:48:46
	 */
	public static class ClassLoaderNotFoundException extends Exception{
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public ClassLoaderNotFoundException(String msg) {
			super(msg);
		}
	}
	public ClassLoader getClassLoader(String classLoaderName){
		if(classLoaderName == null||classLoaderName.isEmpty()){
			return Class.class.getClassLoader();
		}
		
		return classLoaderMap.get(classLoaderName);
	}
	
	public Set<String> getClassLoaderNames(){
		return new HashSet<String>(classLoaderMap.keySet());
	}
	public Map<String,ClassLoader> getClassLoaders(){
		return new HashMap<String, ClassLoader>(classLoaderMap);
	}
	public Map<String,ClassLoader> getClassLoaders(Map<String,ClassLoader> map){
		if(map == null){
			return new HashMap<String, ClassLoader>(classLoaderMap);
		}
		map.putAll(classLoaderMap);
		return map ;
	}
	
	private void installSuccessCallback(String classLoaderName,ClassLoader classLoader){
		for (MyClassLibraryCallback myClassLibraryCallback : myClassLibraryCallbacks.values()) {
			try {
				myClassLibraryCallback.installSuccessCallback(this,classLoaderName, classLoader);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}
	
	private void uninstallSuccessCallback(String classLoaderName, ClassLoader uninstallClassLoader_old){
		for (MyClassLibraryCallback myClassLibraryCallback : myClassLibraryCallbacks.values()) {
			try {
				myClassLibraryCallback.uninstallSuccessCallback(this,classLoaderName, uninstallClassLoader_old);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}
	public void setMyClassLibraryCallbacks(MyClassLibraryCallback... myClassLibraryCallbacks) {
		Map<Class,MyClassLibraryCallback> myClassLibraryCallbackMap = new ConcurrentHashMap<Class,MyClassLibraryCallback>(32);
		for (MyClassLibraryCallback myClassLibraryCallback : myClassLibraryCallbacks) {
			myClassLibraryCallbackMap.put(myClassLibraryCallback.getClass(),myClassLibraryCallback);
		}
		this.myClassLibraryCallbacks = myClassLibraryCallbackMap;
	}
	/** 添加classLibrary的 安装卸载完成回调
	 * 
	 * @param myClassLibraryCallbacks
	 */
	public void addMyClassLibraryCallbacks(MyClassLibraryCallback... myClassLibraryCallbacks) {
		for (MyClassLibraryCallback myClassLibraryCallback : myClassLibraryCallbacks) {
			this.myClassLibraryCallbacks.put(myClassLibraryCallback.getClass(),myClassLibraryCallback);
		}
	}
	
	public void removeMyClassLibraryCallbacks(Class... myClassLibraryCallbackKeys) {
		for (Class myClassLibraryCallbackKey : myClassLibraryCallbackKeys) {
			this.myClassLibraryCallbacks.remove(myClassLibraryCallbackKey);
		}
	}
	
	
}	
